#include "i2c.h"

void i2c_init(void)
{

    // IO引脚初始化

    // I2C重映射
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_I2C1, ENABLE);

    // 初始化pin8 pin 9
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    GPIO_InitTypeDef structure;

    structure.GPIO_Mode = GPIO_Mode_AF_OD;
    structure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
    structure.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_Init(GPIOB, &structure);

    // I2C外设初始化
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);  // 施加复位信号
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE); // 释放复位信号

    I2C_InitTypeDef i2c_structure;
    i2c_structure.I2C_ClockSpeed = 400000;
    i2c_structure.I2C_Mode = I2C_Mode_I2C;
    i2c_structure.I2C_DutyCycle = I2C_DutyCycle_2;

    I2C_Init(I2C1, &i2c_structure);

    I2C_Cmd(I2C1, ENABLE); // 使能I2C1  闭合I2C1的开关
}

int i2c_send_bytes(I2C_TypeDef *I2Cx, uint8_t addr, uint8_t *data, uint16_t size)
{

    /// 等待总线空闲
    while (I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY) == SET)
        ;

    I2C_GenerateSTART(I2Cx, ENABLE); // 产生起始信号

    // 等待起始位发送完成
    while (I2C_GetFlagStatus(I2Cx, I2C_FLAG_SB) == RESET)
        ;

    // 清除AF标志位
    I2C_ClearFlag(I2Cx, I2C_FLAG_AF);

    // 发送地址
    I2C_SendData(I2Cx, addr & 0xfe);

    while (1)
    {

        if (I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR) == SET)
        {
            break;
        }

        if (I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF) == SET)
        {
            // 发送地址失败

            I2C_GenerateSTOP(I2Cx, ENABLE);
            return -1;
        }
    }

    I2C_ReadRegister(I2Cx, I2C_Register_SR1); // 读SR2寄存器清除ADDR标志位
    I2C_ReadRegister(I2Cx, I2C_Register_SR2);

    for (uint16_t i = 0; i < size; i++)
    {
        I2C_SendData(I2Cx, data[i]);

        while (1)
        {

            if (I2C_GetFlagStatus(I2Cx, I2C_FLAG_TXE) == SET)
            {
                break;
            }

            if (I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF) == SET)
            {
                // 发送数据失败

                I2C_GenerateSTOP(I2Cx, ENABLE);
                return -2;
            }
        }

        I2C_SendData(I2Cx, data[i]);
    }

    while (1)
    {
        if (I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF) == SET)
        {
            I2C_GenerateSTOP(I2Cx, ENABLE);
            return -2;
        }
        if (I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF) == SET)
        {
            break;
        }
    }
    // 发送停止位
    I2C_GenerateSTOP(I2Cx, ENABLE);
    return 0;
}

int i2c_recv_bytes(I2C_TypeDef *I2Cx, uint8_t addr, uint8_t *buffer, uint16_t size)
{
    I2C_GenerateSTART(I2Cx, ENABLE); // 产生起始信号
    while (I2C_GetFlagStatus(I2Cx, I2C_FLAG_SB) == RESET)
        ;
    // 寻址
    I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
    I2C_SendData(I2Cx, addr | 0x01);
    while (1)
    {
        if (I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR) == SET)
        {
            break;
        }

        if (I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF) == SET)
        {
            // 发送地址失败

            I2C_GenerateSTOP(I2Cx, ENABLE);
            return -1;
        }
    }

    // 收数据
    if (size == 1)
    {

        I2C_ReadRegister(I2Cx, I2C_Register_SR1);
        I2C_ReadRegister(I2Cx, I2C_Register_SR2); // 清除ADDR标志位
        I2C_AcknowledgeConfig(I2Cx, DISABLE);     // 关闭应答
        I2C_GenerateSTOP(I2Cx, ENABLE);           // 产生停止位
        while (I2C_GetFlagStatus(I2Cx, I2C_FLAG_RXNE) == RESET)
            ;
        buffer[0] = I2C_ReceiveData(I2Cx);
    }
    else if (size == 2)
    {
        I2C_ReadRegister(I2Cx, I2C_Register_SR1);
        I2C_ReadRegister(I2Cx, I2C_Register_SR2); // 清除ADDR标志位
        I2C_AcknowledgeConfig(I2Cx, ENABLE);

        while (I2C_GetFlagStatus(I2Cx, I2C_FLAG_RXNE) == RESET)
            ;

        buffer[0] = I2C_ReceiveData(I2Cx);

        I2C_AcknowledgeConfig(I2Cx, DISABLE);
        I2C_GeneralCallCmd(I2Cx, ENABLE);

        while(I2C_GetFlagStatus(I2Cx,I2C_FLAG_RXNE)==RESET);

        buffer[1] = I2C_ReceiveData(I2Cx);
    }
    else
    {
        I2C_ReadRegister(I2Cx, I2C_Register_SR1);
        I2C_ReadRegister(I2Cx, I2C_Register_SR2); // 清除ADDR标志位
        I2C_AcknowledgeConfig(I2Cx, ENABLE);      // 打开应答

        for (uint16_t i = 0; i < size - 3; i++)
        {
            while (I2C_GetFlagStatus(I2Cx, I2C_FLAG_RXNE) == RESET)
                ;
            buffer[i] = I2C_ReceiveData(I2Cx);
        }

        I2C_AcknowledgeConfig(I2Cx, DISABLE);
        I2C_GenerateSTOP(I2Cx, ENABLE);

        while (I2C_GetFlagStatus(I2Cx, I2C_FLAG_RXNE) == RESET)
            ;
        buffer[size - 1] = I2C_ReceiveData(I2Cx);
    }
}

void led_init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    GPIO_InitTypeDef structure;
    structure.GPIO_Pin = GPIO_Pin_13;
    structure.GPIO_Mode = GPIO_Mode_Out_OD;
    structure.GPIO_Speed = GPIO_Speed_10MHz;

    GPIO_Init(GPIOC, &structure);
}